// 系统用户 - 通用
import { DataTypes, Op, UUIDV4 } from 'sequelize';
import { nanoid } from 'nanoid';
import { get, map, trim } from 'lodash';
import { MySqlModel, getSequelize } from '../db';
import { userTypes, userStatuses } from '../values';
import { encryptPasswordSync, getToday } from '../utils';

class Users extends MySqlModel {
  getPassword(password, salt) {
    return encryptPasswordSync(password, salt);
  }

  getSalt() {
    return nanoid();
  }

  checkPassword(password) {
    return this.password === encryptPasswordSync(password, this.salt);
  }

  async getGrantedHotels() {
    const sequelize = getSequelize();
    const today = getToday();
    if (this.user_type === 'Administrator') {
      return sequelize.models.Hotels.findAll({ order: [['code', 'ASC']] });
    }
    return sequelize.models.Hotels.findAll({
      where: {
        begin_date: { [Op.lte]: today },
        end_date: { [Op.gte]: today }
      },
      include: [{
        model: sequelize.models.UserHotels,
        as: 'user_hotel',
        required: true,
        where: {
          user_id: this.id
        }
      }],
      order: [['code', 'ASC']]
    });
  }

  static async isAdmin(user_id) {
    const user = await this.findById(user_id);
    return get(user, 'user_type') === 'Administrator';
  }
}

Users.init({
  id: {
    type: DataTypes.UUID, unique: 'id', allowNull: false, defaultValue: UUIDV4, validate: { isUUID: 4 }, primaryKey: true, comment: '主键', editable: false
  },
  login_name: {
    type: DataTypes.STRING(50), unique: 'login_name', allowNull: false, validate: { len: [4, 50] }, comment: '用户名'
  },
  salt: {
    type: DataTypes.STRING(64), defaultValue: null, comment: '加密向量'
  },
  password: {
    type: DataTypes.STRING(64),
    defaultValue: null,
    comment: '密文密码'
  },
  password_changed: {
    type: DataTypes.DATE, defaultValue: null, comment: '最后一次修改密码时间'
  },
  user_type: {
    type: DataTypes.STRING(100), allowNull: false, validate: { isIn: [map(userTypes, 'code')] }, comment: '用户账号类型'
  },
  mobile: {
    type: DataTypes.STRING(20), defaultValue: null, comment: '手机'
  },
  email: {
    type: DataTypes.STRING(100), defaultValue: null, validate: { isEmail: true }, comment: '邮箱'
  },
  xlast: {
    type: DataTypes.STRING(50), defaultValue: null, comment: '中文姓氏'
  },
  xfirst: {
    type: DataTypes.STRING(50), defaultValue: null, comment: '中文名字'
  },
  xfull_name: {
    type: DataTypes.STRING(100), defaultValue: null, comment: '中文全名'
  },
  last: {
    type: DataTypes.STRING(50), defaultValue: null, comment: '英文姓氏'
  },
  first: {
    type: DataTypes.STRING(50), defaultValue: null, comment: '英文名字'
  },
  department: {
    type: DataTypes.STRING(50), defaultValue: null, comment: '部门'
  },
  position: {
    type: DataTypes.STRING(50), defaultValue: null, comment: '职位'
  },
  gender_id: {
    type: DataTypes.UUID, allowNull: true, validate: { isUUID: 4 }, comment: '性别'
  },
  last_login: { type: DataTypes.DATE, defaultValue: null, comment: '最近一次登录时间' },
  last_hotel_id: {
    type: DataTypes.UUID, allowNull: true, validate: { isUUID: 4 }, comment: '上次登录主体', editable: false
  },
  error_times: {
    type: DataTypes.INTEGER, defaultValue: 0, allowNull: true, comment: '密码错误次数'
  },
  lock_date: { type: DataTypes.DATE, defaultValue: null, comment: '账号锁定时间' },
  status: {
    type: DataTypes.STRING(50), allowNull: false, validate: { isIn: [map(userStatuses, 'code')] }, comment: '用户状态'
  },
  reference: {
    type: DataTypes.STRING(200), defaultValue: null, comment: '备注'
  },
  created_id: {
    type: DataTypes.UUID, allowNull: false, validate: { isUUID: 4 }, comment: '创建用户', editable: false
  },
  updated_id: {
    type: DataTypes.UUID, allowNull: false, validate: { isUUID: 4 }, comment: '更新用户', editable: false, model: 'Users', column: 'login_name'
  },
  created_at: {
    type: DataTypes.DATE, allowNull: false, editable: false, comment: '创建时间'
  },
  updated_at: {
    type: DataTypes.DATE, allowNull: false, editable: false, comment: '更新时间'
  },
  version: {
    type: DataTypes.INTEGER, allowNull: false, defaultValue: 0, editable: false, comment: '版本控制'
  }
}, {
  sequelize: getSequelize(),
  tableName: 'users',
  comment: '系统用户'
});

Users.beforeValidate((instance, options) => {
  if (instance.isNewRecord) {
    instance.salt = instance.getSalt();
    instance.password = instance.getPassword(instance.password, instance.salt);
  }

  // instance.xfull_name = trim(instance.xlast_name) + trim(instance.xfirst_name);
  // console.log('--------=====', instance.xfull_name);
});

Users.beforeSave((instance, options) => {
  instance.xfull_name = trim(instance.xlast) + trim(instance.xfirst);
  // console.log('--------=====', instance.xfull_name);
});

Users.associate = (models) => {
  Users.hasOne(models.UserHotels, {
    foreignKey: 'user_id',
    sourceKey: 'id',
    constraints: false,
    as: 'user_hotel'
  });
};

Users.beforeDestroy(async (instance, options) => {
  if (instance.last_login) {
    throw new Error('无法删除');
  }
});

Users.afterDestroy(async (instance, options) => {
  const { models } = getSequelize();
  const { UserHotels, UserPermissions } = models;
  const { transaction } = options;
  await Promise.all([
    UserHotels.destroy({ where: { user_id: instance.id }, transaction, individualHooks: true }),
    UserPermissions.destroy({ where: { user_id: instance.id }, transaction, individualHooks: true })
  ]);
});

export default Users;
